ブートストラップローダの詳細
[マスターブートレコードの構造]
マスターブートレコード(MBR)の中でも、その前方446バイトのプログラム領域は、その位置付けを明確にするのが難しい部分だ。現在ではこの領域は、いろいろなOSが自分のブートコードを自由に書くフリーな領域の如く扱われている。
現在は、LinuxのLILO、FreeBSDのboot0、Solarisのブートコードなど、各OSが比較的自由に使っているが、本来PC/AT互換機の一般仕様としては、ここにはIBMとMicrosoftで作成したブートストラップローダというプログラムが書かれることになっている。元来このプログラムはDOSの起動のために作らており、パーティションテーブルなども、このプログラムの仕様の一部として設計されている。
従って、PC/AT互換機に別のアークテクチャからOSが移植されたり、新たに設計されたりするにあたり、この領域は原則として触れてはいけないものだった。つまりここには一切触れずにブートできるようにOS側を設計するべきということになっていた。マスターブートレコードは、言わば一種の聖域として位置付けだった訳だ。
しかし、その性質上、パーティションテーブルは確かに他のOSと共存する上で絶対に侵すことはできなかったが、設計上、ブートストラップローダとパーティションテーブルはきっちりと分かれていた上、ブートストラップローダがマルチブートの機能を一切提供していなかったので、ここにブートストラップローダに単純にマルチブートを機能を追加した独自のローダをインストールする試みがされた。
性質上、案の定、このプログラムを書き換えても、ブートさえしてしまえば、各OSとも全く不都合がなかったため、多くのOSがこの領域に独自のローダを置くようになった。更に多くのサードパティのブートローダが登場し、ここに書かれるようになり、今日に至っている。今ではプログラム領域は自由な領域、パーティションテーブル以降は侵すべからざる聖域という位置付けに事実上なっている訳だ。
もっとも自由な領域とは言っても、上記のような経緯から、あくまでこの領域にはIBMブートストラップローダが存在することが原則となっているので、PC/AT互換機上のOSは独自のローダを持っているものでも、それを使わずに起動できるような仕組みも、別途用意すべきとされており、実際必ず持っている。
つまり、ブートストラップローダは単なるDOSやWindows用のブートコードという地位を越えて、PC/AT互換機一般の標準ブートローダとなっている。従ってこのプログラムの理解なしには、PC/AT互換機のブートの仕組みを完全に理解することはできない。ここではそれについての詳細な解説をしていきたいと思う。
ところで、ブートストラップローダはPC/AT互換機の標準ローダであり、後述するように特に問題さえなければ、何のメッセージも表示せず、ユーザに何かの入力を求めるでもなく、あっという間に進んでしまうプログラムなので、多くの人がその存在に気づいていない、まるで空気のようなプログラムだ。
よくLinuxのLILOをマスターブートレコードに書いた場合、LILOインストール前の状態に戻すために、「LILOを消したい」という人がいる。またSystemCommanderなどのサードパティのブートローダをインストールすると、やはりマスターブートレコードに書かれるので、元の状態に戻すのに、「ブートローダを消して、アンインストールしたい」という人も見かける。しかし単にLILOを消してしまったり、SystemCommanderを消してしまって、マスターブートレコードのプログラム領域に何のデータも無くしてしまっては、OSは一切起動不能になってしまう。
従って厳密には、LILOを消したり、SystemCommanderをアンインストールするというのは、マスターブートレコードのプログラム領域に、もう一度ブートストラップローダを書くということを意味するのだ。しかし上記のようなことを言う人が多いのは、すなわちブートストラップローダの存在を全く意識していない、知らないといった、一種の誤解をしている人が多いからだ。
そんな空気のような存在なので、これのインストールということも勿論意識している人は非常に少ないと思う。しかしプログラムだから、決して自然発生する訳はなく、だれかがこれを書いている。ここでは、どんな時に、誰がこのプログラムを書く(インストールする)のか説明する。
ブートストラップローダのインストールの仕方、及び無意識のうちにインストールされる場面というのは、実は結構沢山あるが、大きく分けて2種類に大別できる。以下にそれを示す。
このうち、1番のAと、2番の各項目が、多くの人が無意識のうちにインストールされる場合だ。
まず、1番の「必ずブートストラップローダがインストールされる場合」だが、Windows98などをインストールすると有無も言わさずインストールされる。これはサードパーティのブートローダの作者からすると、有名な迷惑仕様で、ローダの説明書は必ず注意事項として書いてある。大抵のローダは復旧用の手段を用意している。因みにWindowsNT/2000/XPでは、インストールしただけでは、勝手にブートストラップローダをインストールしたりはしない。
次の「FDISK /MBR」は有名なので、説明するまでもないだろう。ブートストラップローダの復旧(インストール)に使われる最も一般的な方法だ。FDISKコマンドは、Windows9xの起動ディスク、DOS窓、Command Prompt Onlyなどで実行可能だ。
次のWindows2000/XPの回復コンソールのコマンド「fixmbr」はあまり知られていないようだ。ただしWindows2000/XPの回復コンソール自体がWindows2000/XPがインストールされている環境でないと実行できないので、あまり汎用的で便利な方法とはいえない。やはりマルチブートをしている人には、Windows9xの起動ディスクは手放せないだろう。
因みに、これらの行為でブートストラップローダがインストールされるのは、その時点で第1ハードディスクとして認識されているハードディスクのマスターブートレコードのみだ。
2番の「マスターブートレコードにデータがない時のみインストールされる場合」の方は、これによってブートストラップローダがインストールされることは殆ど知られてない。無意識にうちにインストールされる最も典型的な場面だろう。
この「マスターブートレコードにデータがない」というのは、通常は買ったばかりのまっさらなハードディスクの場合だろうが、厳密には単にマスターブートレコードの最終2バイトのブートシグニチャが「0xAA55」でない場合を言う。
従って、実際にはマスターブートレコードにブートコードやパーティション情報が既に書かれていても、ブートシグニチャが例えば「0xBB55」だったりしたら、FDISKなどのパーティションツールや、OSから、そのマスターブートレコード自体が無効扱いされるので、まっさらの(全て00で埋まっている)状態と同様の扱いになる。
厳密に言うと上記のような仕様だが、通常はおかしなブートシグニチャになることはないはずなので(私のように実験のためにわざと書き換えるなどしない限り)、「そのハードディスクではじめてパーティションを作る時」と理解してもらっても、特段不都合はないだろう。
またこちらの場合は、第1ハードディスク以外に領域を作成した場合でも、そのハードディスクのマスターブートレコードにもインストールされる。
FDISKコマンドの実行方法は前述と同じだ。
「WindowsNT/2000/XPで領域の作成」とは、WindowsNT上のディスクアドミニストレータや、Windows2000/XP上のディスクの管理での領域作成の他、インストール時の領域作成フェーズでの作成なども含む。
以前の解説と重複するが、このプログラムの動作概要から書く。
これを踏まえて、ここではもっと突っ込んだ動作検証をしていく。まずこのプログラムは非常に小さいのでバイナリダンプしてみよう。以下にマスターブートレコード全体のバイナリダンプを示す。もしバイナリダンプの意味すらわからない人は、動作解説だけ読んでみてほしい。
[マスターブートレコードのバイナリダンプ]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 00000000 FA 33 C0 8E D0 BC 00 7C 8B F4 50 07 50 1F FB FC ・タ社シ.|偶P.P. 00000010 BF 00 06 B9 00 01 F3 A5 EA 1D 06 00 00 BE BE 07 ソ..ケ..・・...セセ. 00000020 B3 04 80 3C 80 74 0E 80 3C 00 75 1C 83 C6 10 FE ウ.?<?t.?<.u.θ. 00000030 CB 75 EF CD 18 8B 14 8B 4C 02 8B EE 83 C6 10 FE ヒu・.・記.駒θ. 00000040 CB 74 1A 80 3C 00 74 F4 BE 8B 06 AC 3C 00 74 0B ヒt.?<.tセ・ャ<.t. 00000050 56 BB 07 00 B4 0E CD 10 5E EB F0 EB FE BF 05 00 Vサ..エ.ヘ.^・・ソ.. 00000060 BB 00 7C B8 01 02 57 CD 13 5F 73 0C 33 C0 CD 13 サ.|ク..Wヘ._s.3タヘ. 00000070 4F 75 ED BE A3 06 EB D3 BE C2 06 BF FE 7D 81 3D Ouレ」.・セツ.ソ}・ 00000080 55 AA 75 C7 8B F5 EA 00 7C 00 00 49 6E 76 61 6C Uェuヌ寓・|..Inval 00000090 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 62 id partition tab 000000A0 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E 67 le.Error loading 000000B0 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 65 operating syste 000000C0 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 74 m.Missing operat 000000D0 69 6E 67 20 73 79 73 74 65 6D 00 00 00 00 00 00 ing system...... 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 01 ........隲;・... 000001C0 01 00 06 FE 7F 04 3F 00 00 00 86 FA 3F 00 00 00 .....?...・?... 000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ |
赤い部分がブートストラップローダの部分だ。まあ、通常はこんなものを見ても、何が書いてあるのかさっぱり分からないだろう。精々「Invalid Partition Table」といった文字列などが確認され、きっと何かあったらこのメッセージが表示されるのだろうな、くらいだろうか。あとは、446バイトあるプログラム領域だが、実際はブートストラップローダは218バイトしかなく、領域の半分以上が余っていることがわかる。後ろの方(青い部分)にパーティションテーブルがあり、最後(緑の部分)にマジックナンバーがあるのも見える。
いずれにしても、これではプログラムの動作は全く分からないので、この内容を逆アッセンブラしたデータがあるので紹介しよう。
[ブートストラップローダの逆アッセンブラデータ]
This sector is initially loaded into memory at 0000:7c00 but it immediately relocates itself to 0000:0600.
BEGIN: NOW AT 0000:7C00, RELOCATE 0000:7C00 FA CLI disable int's 0000:7C01 33C0 XOR AX,AX set stack seg to 0000 0000:7C03 8ED0 MOV SS,AX 0000:7C05 BC007C MOV SP,7C00 set stack ptr to 7c00 0000:7C08 8BF4 MOV SI,SP SI now 7c00 0000:7C0A 50 PUSH AX 0000:7C0B 07 POP ES ES now 0000:7c00 0000:7C0C 50 PUSH AX 0000:7C0D 1F POP DS DS now 0000:7c00 0000:7C0E FB STI allow int's 0000:7C0F FC CLD clear direction 0000:7C10 BF0006 MOV DI,0600 DI now 0600 0000:7C13 B90001 MOV CX,0100 move 256 words (512 bytes) 0000:7C16 F2 REPNZ move MBR from 0000:7c00 0000:7C17 A5 MOVSW to 0000:0600 0000:7C18 EA1D060000 JMP 0000:061D jmp to NEW_LOCATION NEW_LOCATION: NOW AT 0000:0600 0000:061D BEBE07 MOV SI,07BE point to first table entry 0000:0620 B304 MOV BL,04 there are 4 table entries SEARCH_LOOP1: SEARCH FOR AN ACTIVE ENTRY 0000:0622 803C80 CMP BYTE PTR [SI],80 is this the active entry? 0000:0625 740E JZ FOUND_ACTIVE yes 0000:0627 803C00 CMP BYTE PTR [SI],00 is this an inactive entry? 0000:062A 751C JNZ NOT_ACTIVE no 0000:062C 83C610 ADD SI,+10 incr table ptr by 16 0000:062F FECB DEC BL decr count 0000:0631 75EF JNZ SEARCH_LOOP1 jmp if not end of table 0000:0633 CD18 INT 18 GO TO ROM BASIC FOUND_ACTIVE: FOUND THE ACTIVE ENTRY 0000:0635 8B14 MOV DX,[SI] set DH/DL for INT 13 call 0000:0637 8B4C02 MOV CX,[SI+02] set CH/CL for INT 13 call 0000:063A 8BEE MOV BP,SI save table ptr SEARCH_LOOP2: MAKE SURE ONLY ONE ACTIVE ENTRY 0000:063C 83C610 ADD SI,+10 incr table ptr by 16 0000:063F FECB DEC BL decr count 0000:0641 741A JZ READ_BOOT jmp if end of table 0000:0643 803C00 CMP BYTE PTR [SI],00 is this an inactive entry? 0000:0646 74F4 JZ SEARCH_LOOP2 yes NOT_ACTIVE: MORE THAN ONE ACTIVE ENTRY FOUND 0000:0648 BE8B06 MOV SI,068B display "Invld prttn tbl" DISPLAY_MSG: DISPLAY MESSAGE LOOP 0000:064B AC LODSB get char of message 0000:064C 3C00 CMP AL,00 end of message 0000:064E 740B JZ HANG yes 0000:0650 56 PUSH SI save SI 0000:0651 BB0700 MOV BX,0007 screen attributes 0000:0654 B40E MOV AH,0E output 1 char of message 0000:0656 CD10 INT 10 to the display 0000:0658 5E POP SI restore SI 0000:0659 EBF0 JMP DISPLAY_MSG do it again HANG: HANG THE SYSTEM LOOP 0000:065B EBFE JMP HANG sit and stay! READ_BOOT: READ ACTIVE PARITION BOOT RECORD 0000:065D BF0500 MOV DI,0005 INT 13 retry count INT13RTRY: INT 13 RETRY LOOP 0000:0660 BB007C MOV BX,7C00 0000:0663 B80102 MOV AX,0201 read 1 sector 0000:0666 57 PUSH DI save DI 0000:0667 CD13 INT 13 read sector into 0000:7c00 0000:0669 5F POP DI restore DI 0000:066A 730C JNB INT13OK jmp if no INT 13 0000:066C 33C0 XOR AX,AX call INT 13 and 0000:066E CD13 INT 13 do disk reset 0000:0670 4F DEC DI decr DI 0000:0671 75ED JNZ INT13RTRY if not zero, try again 0000:0673 BEA306 MOV SI,06A3 display "Errr ldng systm" 0000:0676 EBD3 JMP DISPLAY_MSG jmp to display loop INT13OK: INT 13 ERROR 0000:0678 BEC206 MOV SI,06C2 "missing op sys" 0000:067B BFFE7D MOV DI,7DFE point to signature 0000:067E 813D55AA CMP WORD PTR [DI],AA55 is signature correct? 0000:0682 75C7 JNZ DISPLAY_MSG no 0000:0684 8BF5 MOV SI,BP set SI 0000:0686 EA007C0000 JMP 0000:7C00 JUMP TO THE BOOT SECTOR WITH SI POINTING TO PART TABLE ENTRY Messages table. 0000:0680 ........ ........ ......49 6e76616c * Inval* 0000:0690 69642070 61727469 74696f6e 20746162 *id partition tab* 0000:06a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading* 0000:06b0 206f7065 72617469 6e672073 79737465 * operating syste* 0000:06c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat* 0000:06d0 696e6720 73797374 656d00.. ........ *ing system. * |
これを見ても、まださっぱり分からない人が殆どだろう。私もアッセンブラコードを殆どまともに読めないので、これを詳細に解説することはできない。まあそれほど細かな動作は分からなくてもいいと思うので、私が解析できる範囲内で、このアッセンブラコードを解読し、プログラムの動作を追ってみよう。
BEGIN: NOW AT 0000:7C00, RELOCATE 0000:7C00 FA CLI disable int's 0000:7C01 33C0 XOR AX,AX set stack seg to 0000 0000:7C03 8ED0 MOV SS,AX 0000:7C05 BC007C MOV SP,7C00 set stack ptr to 7c00 0000:7C08 8BF4 MOV SI,SP SI now 7c00 0000:7C0A 50 PUSH AX 0000:7C0B 07 POP ES ES now 0000:7c00 0000:7C0C 50 PUSH AX 0000:7C0D 1F POP DS DS now 0000:7c00 0000:7C0E FB STI allow int's 0000:7C0F FC CLD clear direction 0000:7C10 BF0006 MOV DI,0600 DI now 0600 0000:7C13 B90001 MOV CX,0100 move 256 words (512 bytes) 0000:7C16 F2 REPNZ move MBR from 0000:7c00 0000:7C17 A5 MOVSW to 0000:0600 0000:7C18 EA1D060000 JMP 0000:061D jmp to NEW_LOCATION NEW_LOCATION: NOW AT 0000:0600 0000:061D BEBE07 MOV SI,07BE point to first table entry 0000:0620 B304 MOV BL,04 there are 4 table entries |
まず、MBR自身はメモリ上の0000:7C00というアドレスにロードされ、この位置でBIOSから実行される。この位置はその後ブートセクターなどが皆ロードされるお決まりの位置だ。つまりこのブートストラップローダが、やがてブートセクターをロードする時に困らないように、一旦まず最初に自分自身を、0000:06000という別の場所に移動する。
新しい場所に移動したら、今まで実行した直後の部分から、自分自身の実行を続ける。こんな動きがいかにも、bootstrapの語源のイディオムらしい部分だ。
新しい場所での最初の仕事は次のステップのための、パーティションテーブルエントリ数「4」を設定することだ。
SEARCH_LOOP1: SEARCH FOR AN ACTIVE ENTRY 0000:0622 803C80 CMP BYTE PTR [SI],80 is this the active entry? 0000:0625 740E JZ FOUND_ACTIVE yes 0000:0627 803C00 CMP BYTE PTR [SI],00 is this an inactive entry? 0000:062A 751C JNZ NOT_ACTIVE no 0000:062C 83C610 ADD SI,+10 incr table ptr by 16 0000:062F FECB DEC BL decr count 0000:0631 75EF JNZ SEARCH_LOOP1 jmp if not end of table 0000:0633 CD18 INT 18 GO TO ROM BASIC FOUND_ACTIVE: FOUND THE ACTIVE ENTRY 0000:0635 8B14 MOV DX,[SI] set DH/DL for INT 13 call 0000:0637 8B4C02 MOV CX,[SI+02] set CH/CL for INT 13 call 0000:063A 8BEE MOV BP,SI save table ptr |
パーティションテーブルを先頭から探索し、テーブルの先頭の1バイト(ブートフラグ、アクティブフラグ)が、0x80かどうか比較する。0x80だったら、この領域がアクティブな基本領域なので、その領域情報全体をセーブすると共に先頭位置(ブートセクターの位置)をパラメータに指定して、INT13Hでそのセクターをロードする準備をする。
0x80でない場合、次に0x00か確認する。0x00だったら、このループ(SEARCH_LOOP1)の先頭に戻り、次のテーブルの検査をする。
もしブートフラグが0x00で無かったら、つまり0x80でも0x00でもない無効な値が入っているということなので、後述する「NO ACTIVE」ルーチンに飛び、「Invalid partition table」というエラーメッセージを出力することになる。(やがてシステム停止する)
このループを4回繰り返し(4つの全テーブル分)、全部ブートフラグが0x00だったら、アクティブな基本領域が一つも無かったということで、INT18Hを発行して、ROM BASICに飛んで、ブートストラップローダの実行は停止してしまう。そのあとの動作はBIOS次第だが、大抵は単なる起動の停止(HANG)になるだろう。
SEARCH_LOOP2: MAKE SURE ONLY ONE ACTIVE ENTRY 0000:063C 83C610 ADD SI,+10 incr table ptr by 16 0000:063F FECB DEC BL decr count 0000:0641 741A JZ READ_BOOT jmp if end of table 0000:0643 803C00 CMP BYTE PTR [SI],00 is this an inactive entry? 0000:0646 74F4 JZ SEARCH_LOOP2 yes NOT_ACTIVE: MORE THAN ONE ACTIVE ENTRY FOUND 0000:0648 BE8B06 MOV SI,068B display "Invld prttn tbl" |
前ステップで、アクティブな基本領域が見つかった場合にこの処理に来る。残りのテーブルのアクティブフラグが全部0x00かどうか確認する。もし0x00以外があったら(0x80、つまり他にもアクティブな基本領域があったり、それ以外、つまり無効な値があった場合)、やはりエラーメッセージ「Invalid
partition table」を発行する準備をする。
残りが全部0x00だったら(すなわち無効な値もなく、アクティブな基本領域も一つしかなかった)、いよいよアクティブな基本領域のブートセクターをロードするため、後述する「READE_BOOT」ルーチンへ飛ぶ。
DISPLAY_MSG: DISPLAY MESSAGE LOOP 0000:064B AC LODSB get char of message 0000:064C 3C00 CMP AL,00 end of message 0000:064E 740B JZ HANG yes 0000:0650 56 PUSH SI save SI 0000:0651 BB0700 MOV BX,0007 screen attributes 0000:0654 B40E MOV AH,0E output 1 char of message 0000:0656 CD10 INT 10 to the display 0000:0658 5E POP SI restore SI 0000:0659 EBF0 JMP DISPLAY_MSG do it again HANG: HANG THE SYSTEM LOOP 0000:065B EBFE JMP HANG sit and stay! |
エラーメッセージの出力はこのルーチンが一手に引き受ける。指定位置に設定されたメッセージ文字列をINT10Hで1文字ずつ画面に表示して、全文字表示し終わったら、システムを停止(ハング)させる。ブート作業はここで停止することになる。
READ_BOOT: READ ACTIVE PARITION BOOT RECORD 0000:065D BF0500 MOV DI,0005 INT 13 retry count INT13RTRY: INT 13 RETRY LOOP 0000:0660 BB007C MOV BX,7C00 0000:0663 B80102 MOV AX,0201 read 1 sector 0000:0666 57 PUSH DI save DI 0000:0667 CD13 INT 13 read sector into 0000:7c00 0000:0669 5F POP DI restore DI 0000:066A 730C JNB INT13OK jmp if no INT 13 0000:066C 33C0 XOR AX,AX call INT 13 and 0000:066E CD13 INT 13 do disk reset 0000:0670 4F DEC DI decr DI 0000:0671 75ED JNZ INT13RTRY if not zero, try again 0000:0673 BEA306 MOV SI,06A3 display "Errr ldng systm" 0000:0676 EBD3 JMP DISPLAY_MSG jmp to display loop |
いよいよここで、アクティブな基本領域のブートセクターを以前自分がいたメモリ位置「0000:7C00」にロードする。DISK BIOS(INT13H)でロードを行う。読み込みエラーが起きても、4回リトライを行う(つまり全部で5回やる)。
5回頑張っても、読み込めなかった場合、エラーメッセージ「Error loading operating system」を発行する準備をして、前述の「DISPLAY_MSG」ルーチンに飛ぶ。(やがてこのメッセージを出力してシステム停止する)
INT13OK: INT 13 ERROR 0000:0678 BEC206 MOV SI,06C2 "missing op sys" 0000:067B BFFE7D MOV DI,7DFE point to signature 0000:067E 813D55AA CMP WORD PTR [DI],AA55 is signature correct? 0000:0682 75C7 JNZ DISPLAY_MSG no 0000:0684 8BF5 MOV SI,BP set SI 0000:0686 EA007C0000 JMP 0000:7C00 JUMP TO THE BOOT SECTOR WITH SI POINTING TO PART TABLE ENTRY |
ブートセクターのロードに成功したら、最後にそのブートセクターの正当性の検査を行う。ブートセクターの最後の2バイトが「0xAA55」かどうかで、正当性のチェックを行う。
もし0xAA55でなかったら、「Missing operating system」というエラーメッセージをセットしてメッセージ出力ルーチンに飛ぶ。
正当な値であったら、ブートセクターに実行制御を移して、ブートストラップローダの仕事は無事終えることになる。
細かなステップまでは説明してないが、ブートストラップローダの動作はこれでかなり詳細に分かったと思う。どんなエラーメッセージが、どういう場合に出力されるかなども、よく分かると思う。
ブートストラップローダもプログラムである以上、バージョンというものがある。存在そのものが意識されていないくらいなので、そのバージョンがあることを意識している人は、更に少ないだろう。表示画面のあるブートローダなどでは、バージョン表示がされるものがあるが、ブートストラップローダは通常は画面に何も出てこないので、バイナリ比較でもしないとバージョンの確認はできない。
あまり過去のものは私も知らないが、現在ざっと以下の3つのバージョンの存在を確認している。もっともバージョン番号のようなものの存在は確認できなかった。
前述のプログラムの構造で逆アッセブラしたものは、上記のベーシック版だ。だからここではもう説明しない。
次のFAT32対応版だが、まずバイナリダンプしたものをみよう。
[FAT32対応ブートストラップローダのバイナリダンプ]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 00000000 33 C0 8E D0 BC 00 7C FB 50 07 50 1F FC BE 1B 7C 3タ社シ.|P.P.・.| 00000010 BF 1B 06 50 57 B9 E5 01 F3 A4 CB BE BE 07 B1 04 ソ..PWケ・、ヒセセ.ア. 00000020 38 2C 7C 09 75 15 83 C6 10 E2 F5 CD 18 8B 14 8B 8,|.u.θ.糢ヘ.・駒 00000030 EE 83 C6 10 49 74 16 38 2C 74 F6 BE 10 07 4E AC θ.It.8,tセ..Nャ 00000040 3C 00 74 FA BB 07 00 B4 0E CD 10 EB F2 89 46 25 <.tサ..エ.ヘ.・宇% 00000050 96 8A 46 04 B4 06 3C 0E 74 11 B4 0B 3C 0C 74 05 槙F.エ.<.t.エ.<.t. 00000060 3A C4 75 2B 40 C6 46 25 06 75 24 BB AA 55 50 B4 :トu+@ニF%.u$サェUPエ 00000070 41 CD 13 58 72 16 81 FB 55 AA 75 10 F6 C1 01 74 Aヘ.Xr.・Uェu.チ.t 00000080 0B 8A E0 88 56 24 C7 06 A1 06 EB 1E 88 66 04 BF .癌・$ヌ.。.・・.ソ 00000090 0A 00 B8 01 02 8B DC 33 C9 83 FF 05 7F 03 8B 4E ..ク..衿3ノ・...起 000000A0 25 03 4E 02 CD 13 72 29 BE 46 07 81 3E FE 7D 55 %.N.ヘ.r)セF.・}U 000000B0 AA 74 5A 83 EF 05 7F DA 85 F6 75 83 BE 27 07 EB ェtZ・..レ・u・'.・ 000000C0 8A 98 91 52 99 03 46 08 13 56 0A E8 12 00 5A EB ・R・F..V.・.Z・ 000000D0 D5 4F 74 E4 33 C0 CD 13 EB B8 00 00 00 00 00 00 Ot・タヘ.・...... 000000E0 56 33 F6 56 56 52 50 06 53 51 BE 10 00 56 8B F4 V3VVRP.SQセ..V偶 000000F0 50 52 B8 00 42 8A 56 24 CD 13 5A 58 8D 64 10 72 PRク.B碍$ヘ.ZX硬.r 00000100 0A 40 75 01 42 80 C7 02 E2 F7 F8 5E C3 EB 74 49 .@u.B?ヌ.糯^テ・I 00000110 6E 76 61 6C 69 64 20 70 61 72 74 69 74 69 6F 6E nvalid partition 00000120 20 74 61 62 6C 65 00 45 72 72 6F 72 20 6C 6F 61 table.Error loa 00000130 64 69 6E 67 20 6F 70 65 72 61 74 69 6E 67 20 73 ding operating s 00000140 79 73 74 65 6D 00 4D 69 73 73 69 6E 67 20 6F 70 ystem.Missing op 00000150 65 72 61 74 69 6E 67 20 73 79 73 74 65 6D 00 00 erating system.. 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000180 00 00 00 8B FC 1E 57 8B F5 CB 00 00 00 00 00 00 ...屈.W寓ヒ...... 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 01 ..............?. 000001C0 01 00 0B FE 3F CF 3F 00 00 00 91 FC 32 00 00 00 ...?マ?...只2... 000001D0 01 D0 0F FE FF FF D0 FC 32 00 A9 64 F0 01 00 00 .ミ.ミ・.ゥd・.. 000001E0 C1 FF 0C FE FF FF 79 61 23 02 B9 09 3D 00 00 00 チ.ya#.ケ.=... 000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uェ |
ベーシック版と比べるとかなり違うのがわかる。サイズも350バイトあり、132バイトも多いのだ。以下にこれを逆アッセンブラしたデータを示す。
[FAT32対応ブートストラップローダの逆アッセンブラデータ]
--- disas start --- 000000 33C0 XOR AX,AX ; 3タ 000002 8ED0 MOV SS,AX ; 社 000004 BC 007C MOV SP,7C00h ; シ.| 000007 FB STI ; . 000008 50 PUSH AX ; P 000009 07 POP ES ; . 00000A 50 PUSH AX ; P 00000B 1F POP DS ; . 00000C FC CLD ; . 00000D BE 1B7C MOV SI,7C1Bh ; セ.| 000010 BF 1B06 MOV DI,061Bh ; ソ.. 000013 50 PUSH AX ; P 000014 57 PUSH DI ; W 000015 B9 E501 MOV CX,01E5h ; ケ.. 000018 F3 REP ; . 000019 A4 MOVSB ; 、 00001A CB RETF ;<========== ヒ 00001B BE BE07 MOV SI,07BEh ; セセ. 00001E B1 04 MOV CL,04h ; ア. _00000020 382C CMP byte ptr[SI],CH ; 8, 000022 7C 09 JL _0000002D ;if SF!=OF,----->v 0000002D |. 000024 75 15 JNZ _0000003B ;if !ZF,----->v 0000003B u. 000026 83C6 10 ADD SI,+10h ; θ. 000029 E2 F5 LOOP _00000020 ;if --CX,----->^ 00000020 糢 00002B CD 18 INT 18h ;@D_ = BASIC Loader ;INT 18h<=====> ヘ. _0000002D 8B14 MOV DX,word ptr[SI] ; .. 00002F 8BEE MOV BP,SI ; 駒 _00000031 83C6 10 ADD SI,+10h ; θ. 000034 49 DEC CX ; I 000035 74 16 JZ _0000004D ;if ZF,----->v 0000004D t. 000037 382C CMP byte ptr[SI],CH ; 8, 000039 74 F6 JZ _00000031 ;if ZF,----->^ 00000031 t. _0000003B BE 1007 MOV SI,0710h ; セ.. _0000003E 4E DEC SI ; N _0000003F AC LODSB ; ャ 000040 3C 00 CMP AL,00h ; <. 000042 74 FA JZ _0000003E ;if ZF,----->^ 0000003E t. 000044 BB 0700 MOV BX,0007h ; サ.. 000047 B4 0E MOV AH,0Eh ; エ. 000049 CD 10 INT 10h ;@D_0E = Write TTY ;INT 10h<=====> ヘ. _0000004B EB F2 JMP _0000003F ;----->^ 0000003F ・ _0000004D 8946 25 MOV word ptr[BP+25h],AX ; 宇% 000050 96 XCHG AX,SI ; . 000051 8A46 04 MOV AL,byte ptr[BP+04h] ; 皆. 000054 B4 06 MOV AH,06h ; エ. 000056 3C 0E CMP AL,0Eh ; <. 000058 74 11 JZ _0000006B ;if ZF,----->v 0000006B t. 00005A B4 0B MOV AH,0Bh ; エ. 00005C 3C 0C CMP AL,0Ch ; <. 00005E 74 05 JZ _00000065 ;if ZF,----->v 00000065 t. 000060 3AC4 CMP AL,AH ; :ト 000062 75 2B JNZ _0000008F ;if !ZF,----->v 0000008F u+ 000064 40 INC AX ; @ _00000065 C646 25 06 MOV byte ptr[BP+25h],06h ; ニF%. 000069 75 24 JNZ _0000008F ;if !ZF,----->v 0000008F u$ _0000006B BB AA55 MOV BX,55AAh ; サェU 00006E 50 PUSH AX ; P 00006F B4 41 MOV AH,41h ; エA 000071 CD 13 INT 13h ;@D_41 = Check for Extension Support ;INT 13h<=====> ヘ. 000073 58 POP AX ; X 000074 72 16 JB _0000008C ;if CF,----->v 0000008C r. 000076 81FB 55AA CMP BX,AA55h ; ・Uェ 00007A 75 10 JNZ _0000008C ;if !ZF,----->v 0000008C u. 00007C F6C1 01 TEST CL,01h ; チ. 00007F 74 0B JZ _0000008C ;if ZF,----->v 0000008C t. 000081 8AE0 MOV AH,AL ; 癌 000083 8856 24 MOV byte ptr[BP+24h],DL ; ・$ 000086 C706 A106 EB1E MOV word ptr[06A1h],1EEBh ; ヌ.。... _0000008C 8866 04 MOV byte ptr[BP+04h],AH ; ・. _0000008F BF 0A00 MOV DI,000Ah ; ソ.. _00000092 B8 0102 MOV AX,0201h ; ク.. 000095 8BDC MOV BX,SP ; 衿 000097 33C9 XOR CX,CX ; 3ノ 000099 83FF 05 CMP DI,+05h ; ・. 00009C 7F 03 JG _000000A1 ;if !ZF && SF==OF,----->v 000000A1 .. 00009E 8B4E 25 MOV CX,word ptr[BP+25h] ; 起% _000000A1 034E 02 ADD CX,word ptr[BP+02h] ; .N. 0000A4 CD 13 INT 13h ;@D_xx = Unknown ;INT 13h<=====> ヘ. _000000A6 72 29 JB _000000D1 ;if CF,----->v 000000D1 r) 0000A8 BE 4607 MOV SI,0746h ; セF. 0000AB 813E FE7D 55AA CMP word ptr[7DFEh],AA55h ; ・.}Uェ 0000B1 74 5A JZ _0000010D ;if ZF,----->v 0000010D tZ 0000B3 83EF 05 SUB DI,+05h ; ・. 0000B6 7F DA JG _00000092 ;if !ZF && SF==OF,----->^ 00000092 .レ _000000B8 85F6 TEST SI,SI ; ・ 0000BA 75 83 JNZ _0000003F ;if !ZF,----->^ 0000003F u. 0000BC BE 2707 MOV SI,0727h ; セ'. 0000BF EB 8A JMP _0000004B ;----->^ 0000004B ・ 0000C1 98 CBW ; . 0000C2 91 XCHG AX,CX ; . 0000C3 52 PUSH DX ; R 0000C4 99 CWD ; . 0000C5 0346 08 ADD AX,word ptr[BP+08h] ; .F. 0000C8 1356 0A ADC DX,word ptr[BP+0Ah] ; .V. 0000CB E8 1200 CALL _000000E0 ;<---------->v 000000E0 ... 0000CE 5A POP DX ; Z 0000CF EB D5 JMP _000000A6 ;----->^ 000000A6 ・ _000000D1 4F DEC DI ; O 0000D2 74 E4 JZ _000000B8 ;if ZF,----->^ 000000B8 t. 0000D4 33C0 XOR AX,AX ; 3タ 0000D6 CD 13 INT 13h ;@D_00 = Disk Reset ;INT 13h<=====> ヘ. 0000D8 EB B8 JMP _00000092 ;----->^ 00000092 ・ 0000DA 000000000000 DB 00h,00h,00h,00h,00h,00h ;?? ...... _000000E0 56 PUSH SI ; V 0000E1 33F6 XOR SI,SI ; 3. 0000E3 56 PUSH SI ; V 0000E4 56 PUSH SI ; V 0000E5 52 PUSH DX ; R 0000E6 50 PUSH AX ; P 0000E7 06 PUSH ES ; . 0000E8 53 PUSH BX ; S 0000E9 51 PUSH CX ; Q 0000EA BE 1000 MOV SI,0010h ; セ.. 0000ED 56 PUSH SI ; V 0000EE 8BF4 MOV SI,SP ; 偶 0000F0 50 PUSH AX ; P 0000F1 52 PUSH DX ; R 0000F2 B8 0042 MOV AX,4200h ; ク.B 0000F5 8A56 24 MOV DL,byte ptr[BP+24h] ; 碍$ 0000F8 CD 13 INT 13h ;@D_42 = Extended Read ;INT 13h<=====> ヘ. 0000FA 5A POP DX ; Z 0000FB 58 POP AX ; X 0000FC 8D64 10 LEA SP,[SI+10h] ; 硬. 0000FF 72 0A JB _0000010B ;if CF,----->v 0000010B r. _00000101 40 INC AX ; @ 000102 75 01 JNZ _00000105 ;if !ZF,----->v 00000105 u. 000104 42 INC DX ; B _00000105 80C7 02 ADD BH,02h ; .ヌ. 000108 E2 F7 LOOP _00000101 ;if --CX,----->^ 00000101 糯 00010A F8 CLC ; . _0000010B 5E POP SI ; ^ 00010C C3 RET ;<===== テ _0000010D EB 74 JMP _00000183 ;----->v 00000183 ・ 00010F 496E76616C696420 DB 'I','n','v','a','l','i','d',' ' ;?? Invalid 000117 706172746974696F DB 'p','a','r','t','i','t','i','o' ;?? partitio 00011F 6E207461626C6500 DB 'n',' ','t','a','b','l','e',00h ;?? n table. 000127 4572726F72206C6F DB 'E','r','r','o','r',' ','l','o' ;?? Error lo 00012F 6164696E67206F70 DB 'a','d','i','n','g',' ','o','p' ;?? ading op 000137 65726174696E6720 DB 'e','r','a','t','i','n','g',' ' ;?? erating 00013F 73797374656D004D DB 's','y','s','t','e','m',00h,'M' ;?? system.M 000147 697373696E67206F DB 'i','s','s','i','n','g',' ','o' ;?? issing o 00014F 7065726174696E67 DB 'p','e','r','a','t','i','n','g' ;?? perating 000157 2073797374656D00 DB ' ','s','y','s','t','e','m',00h ;?? system. 00015F 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000167 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00016F 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000177 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00017F 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000187 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00018F 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000197 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00019F 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001A7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001AF 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001B7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001BF 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001C7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001CF 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001D7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001DF 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001E7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001EF 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001F7 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001FF 00 DB 00h ;?? . --- disas ennded with rc=0 --- |
私自身逆アッセンブルを正確に解説できないが、動作検証した結果などを踏まえて、ベーシック版との違いを説明する。
まず大きな違いは、FAT32のバックアップブートセクターに対応している点だ。FAT32ではブートセクターが破壊された場合に備えて、そのバックアップを持っている。デフォルトではブートセクターの6セクター後ろだが、一応ブートセクターのBPBにもその位置が書いてある。もっともBPBに書いてあるバックアップブートセクター位置は参照されていないようで、必ず6セクター後ろを見に行く。
もし正規のブートセクター(先頭セクター)が無効であった場合(ブートシグニチャが0xAA55でない)、ベーシック版では、「Missing operating system」というエラーメッセージを出力して停止してしまうが、FAT32対応版は、バックアップブートセクターの読み込みを試みる。これを試みても更に有効なブートセクターが見つからない場合のみ、前述のエラーメッセージを出力して停止する。
もう一つのベーシック版との大きな違いはLBA対応だ。ブートしようとするパーティションがFAT16X(ID 0x0C)、FAT32X(ID 0x0E)の場合、CHSでなくLBAモードでセクターの読み出しを行う。従って8GB以降にあるこれらの領域からブートセクターをロードすることが可能になっている。
ただし前述のようにFAT16XとFAT32Xの領域にしか、LBAモードを使わないので、NTFSやLinuxのext2fsなどが8GB以降にある場合はロードすることはできない。
最後に完全LBA対応版の場合だ。
[完全LBA対応のブートストラップローダのバイナリダンプ]
OFFSET +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 00000000 33 C0 8E D0 BC 00 7C FB 50 07 50 1F FC BE 1B 7C 3タ社シ.|P.P.・.| 00000010 BF 1B 06 50 57 B9 E5 01 F3 A4 CB BD BE 07 B1 04 ソ..PWケ・、ヒスセ.ア. 00000020 38 6E 00 7C 09 75 13 83 C5 10 E2 F4 CD 18 8B F5 8n.|.u.η.糜ヘ.寓 00000030 83 C6 10 49 74 19 38 2C 74 F6 A0 B5 07 B4 07 8B θ.It.8,tオ.エ.愚 00000040 F0 AC 3C 00 74 FC BB 07 00 B4 0E CD 10 EB F2 88 ャ<.t・..エ.ヘ.・・ 00000050 4E 10 E8 46 00 73 2A FE 46 10 80 7E 04 0B 74 0B .錻.s*F.?~..t. 00000060 80 7E 04 0C 74 05 A0 B6 07 75 D2 80 46 02 06 83 ?~..t.カ.uメ?F..ェ 00000070 46 08 06 83 56 0A 00 E8 21 00 73 05 A0 B6 07 EB ..シ..・.s.カ.・ 00000080 BC 81 3E FE 7D 55 AA 74 0B 80 7E 10 00 74 C8 A0 ・}Uェt.?~..tネ 00000090 B7 07 EB A9 8B FC 1E 57 8B F5 CB BF 05 00 8A 56 キ.・屈.W寓ヒソ..碍 000000A0 00 B4 08 CD 13 72 23 8A C1 24 3F 98 8A DE 8A FC .エ.ヘ.r#潅$?・゙棄 000000B0 43 F7 E3 8B D1 86 D6 B1 06 D2 EE 42 F7 E2 39 56 C繼ム・ア.メ^9V 000000C0 0A 77 23 72 05 39 46 08 73 1C B8 01 02 BB 00 7C .w#r.9F.s.ク..サ.| 000000D0 8B 4E 02 8B 56 00 CD 13 73 51 4F 74 4E 32 E4 8A 起.儀.ヘ.sQOtN2芒 000000E0 56 00 CD 13 EB E4 8A 56 00 60 BB AA 55 B4 41 CD V.ヘ.・碍.`サェUエAヘ 000000F0 13 72 36 81 FB 55 AA 75 30 F6 C1 01 74 2B 61 60 .r6・Uェu0チ.t+a` 00000100 6A 00 6A 00 FF 76 0A FF 76 08 6A 00 68 00 7C 6A j.j.v.v.j.h.|j 00000110 01 6A 10 B4 42 8B F4 CD 13 61 61 73 0E 4F 74 0B .j.エB偶ヘ.aas.Ot. 00000120 32 E4 8A 56 00 CD 13 EB D6 61 F9 C3 49 6E 76 61 2芒V.ヘ.・aテInva 00000130 6C 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 lid partition ta 00000140 62 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E ble.Error loadin 00000150 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst 00000160 65 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 em.Missing opera 00000170 74 69 6E 67 20 73 79 73 74 65 6D 00 00 00 00 00 ting system..... 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001B0 00 00 00 00 00 2C 44 63 00 00 92 83 00 00 80 01 .....,Dc..茶..?. 000001C0 01 00 07 FE 7F 05 3F 00 00 00 47 39 40 00 00 00 .....?...G9@... 000001D0 41 06 05 FE BF 84 86 39 40 00 BF E2 5D 00 00 00 A..ソф9@.ソ秕... 000001E0 81 85 BE FE BF 85 45 1C 9E 00 C1 3E 00 00 00 00 ≦セソ・.・チ>.... 000001F0 81 86 82 FE FF BD 06 5B 9E 00 38 7B 4C 00 55 AA ≧・ス.[・8{L.Uェ |
FAT32対応版よりも更にサイズが大きくなり、379バイトある。以下に逆アッセンブラしたデータを示す。
[完全LBA対応のブートストラップローダの逆アッセンブラデータ]
000000 33C0 XOR AX,AX ; 3タ 000002 8ED0 MOV SS,AX ; 社 000004 BC 007C MOV SP,7C00h ; シ.| 000007 FB STI ; . 000008 50 PUSH AX ; P 000009 07 POP ES ; . 00000A 50 PUSH AX ; P 00000B 1F POP DS ; . 00000C FC CLD ; . 00000D BE 1B7C MOV SI,7C1Bh ; セ.| 000010 BF 1B06 MOV DI,061Bh ; ソ.. 000013 50 PUSH AX ; P 000014 57 PUSH DI ; W 000015 B9 E501 MOV CX,01E5h ; ケ.. 000018 F3 REP ; . 000019 A4 MOVSB ; 、 00001A CB RETF ;<========== ヒ 00001B BD BE07 MOV BP,07BEh ; スセ. 00001E B1 04 MOV CL,04h ; ア. _00000020 386E 00 CMP byte ptr[BP+00h],CH ; 8n. 000023 7C 09 JL _0000002E ;if SF!=OF,----->v 0000002E |. 000025 75 13 JNZ _0000003A ;if !ZF,----->v 0000003A u. 000027 83C5 10 ADD BP,+10h ; η. 00002A E2 F4 LOOP _00000020 ;if --CX,----->^ 00000020 糜 00002C CD 18 INT 18h ;@D_ = BASIC Loader ;INT 18h<=====> ヘ. _0000002E 8BF5 MOV SI,BP ; 寓 _00000030 83C6 10 ADD SI,+10h ; θ. 000033 49 DEC CX ; I 000034 74 19 JZ _0000004F ;if ZF,----->v 0000004F t. 000036 382C CMP byte ptr[SI],CH ; 8, 000038 74 F6 JZ _00000030 ;if ZF,----->^ 00000030 t. _0000003A A0 B507 MOV AL,byte ptr[07B5h] ; .オ. _0000003D B4 07 MOV AH,07h ; エ. 00003F 8BF0 MOV SI,AX ; 愚 _00000041 AC LODSB ; ャ _00000042 3C 00 CMP AL,00h ; <. 000044 74 FC JZ _00000042 ;if ZF,----->^ 00000042 t. 000046 BB 0700 MOV BX,0007h ; サ.. 000049 B4 0E MOV AH,0Eh ; エ. 00004B CD 10 INT 10h ;@D_0E = Write TTY ;INT 10h<=====> ヘ. 00004D EB F2 JMP _00000041 ;----->^ 00000041 ・ _0000004F 884E 10 MOV byte ptr[BP+10h],CL ; ・. 000052 E8 4600 CALL _0000009B ;<---------->v 0000009B 錻. 000055 73 2A JNB _00000081 ;if !CF,----->v 00000081 s* _00000057 FE46 10 INC byte ptr[BP+10h] ; .F. 00005A 807E 04 0B CMP byte ptr[BP+04h],0Bh ; .~.. 00005E 74 0B JZ _0000006B ;if ZF,----->v 0000006B t. 000060 807E 04 0C CMP byte ptr[BP+04h],0Ch ; .~.. 000064 74 05 JZ _0000006B ;if ZF,----->v 0000006B t. 000066 A0 B607 MOV AL,byte ptr[07B6h] ; .カ. 000069 75 D2 JNZ _0000003D ;if !ZF,----->^ 0000003D uメ _0000006B 8046 02 06 ADD byte ptr[BP+02h],06h ; .F.. 00006F 8346 08 06 ADD word ptr[BP+08h],+06h ; ェ.. 000073 8356 0A 00 ADC word ptr[BP+0Ah],+00h ; シ.. 000077 E8 2100 CALL _0000009B ;<---------->v 0000009B ・. 00007A 73 05 JNB _00000081 ;if !CF,----->v 00000081 s. 00007C A0 B607 MOV AL,byte ptr[07B6h] ; .カ. 00007F EB BC JMP _0000003D ;----->^ 0000003D ・ _00000081 813E FE7D 55AA CMP word ptr[7DFEh],AA55h ; ・.}Uェ 000087 74 0B JZ _00000094 ;if ZF,----->v 00000094 t. 000089 807E 10 00 CMP byte ptr[BP+10h],00h ; .~.. 00008D 74 C8 JZ _00000057 ;if ZF,----->^ 00000057 tネ 00008F A0 B707 MOV AL,byte ptr[07B7h] ; .キ. 000092 EB A9 JMP _0000003D ;----->^ 0000003D ・ _00000094 8BFC MOV DI,SP ; 屈 000096 1E PUSH DS ; . 000097 57 PUSH DI ; W 000098 8BF5 MOV SI,BP ; 寓 00009A CB RETF ;<========== ヒ _0000009B BF 0500 MOV DI,0005h ; ソ.. 00009E 8A56 00 MOV DL,byte ptr[BP+00h] ; 碍. 0000A1 B4 08 MOV AH,08h ; エ. 0000A3 CD 13 INT 13h ;@D_08 = Read Drive Parm ;INT 13h<=====> ヘ. 0000A5 72 23 JB _000000CA ;if CF,----->v 000000CA r# 0000A7 8AC1 MOV AL,CL ; 潅 0000A9 24 3F AND AL,3Fh ; $? 0000AB 98 CBW ; . 0000AC 8ADE MOV BL,DH ; 巌 0000AE 8AFC MOV BH,AH ; 棄 0000B0 43 INC BX ; C 0000B1 F7E3 MUL BX ; 0000B3 8BD1 MOV DX,CX ; 錦 0000B5 86D6 XCHG DH,DL ; ・ 0000B7 B1 06 MOV CL,06h ; ア. 0000B9 D2EE SHR DH,CL ; メ. 0000BB 42 INC DX ; B 0000BC F7E2 MUL DX ; 0000BE 3956 0A CMP word ptr[BP+0Ah],DX ; 9V. 0000C1 77 23 JA _000000E6 ;if !OF && !ZF,----->v 000000E6 w# 0000C3 72 05 JB _000000CA ;if CF,----->v 000000CA r. 0000C5 3946 08 CMP word ptr[BP+08h],AX ; 9F. 0000C8 73 1C JNB _000000E6 ;if !CF,----->v 000000E6 s. _000000CA B8 0102 MOV AX,0201h ; ク.. 0000CD BB 007C MOV BX,7C00h ; サ.| 0000D0 8B4E 02 MOV CX,word ptr[BP+02h] ; 起. 0000D3 8B56 00 MOV DX,word ptr[BP+00h] ; 儀. 0000D6 CD 13 INT 13h ;@D_02 = Read Sector ;INT 13h<=====> ヘ. 0000D8 73 51 JNB _0000012B ;if !CF,----->v 0000012B sQ 0000DA 4F DEC DI ; O 0000DB 74 4E JZ _0000012B ;if ZF,----->v 0000012B tN 0000DD 32E4 XOR AH,AH ; 2. 0000DF 8A56 00 MOV DL,byte ptr[BP+00h] ; 碍. 0000E2 CD 13 INT 13h ;@D_00 = Disk Reset ;INT 13h<=====> ヘ. 0000E4 EB E4 JMP _000000CA ;----->^ 000000CA ・ _000000E6 8A56 00 MOV DL,byte ptr[BP+00h] ; 碍. 0000E9 60 PUSHA ; ` 0000EA BB AA55 MOV BX,55AAh ; サェU 0000ED B4 41 MOV AH,41h ; エA 0000EF CD 13 INT 13h ;@D_41 = Check for Extension Support ;INT 13h<=====> ヘ. 0000F1 72 36 JB _00000129 ;if CF,----->v 00000129 r6 0000F3 81FB 55AA CMP BX,AA55h ; ・Uェ 0000F7 75 30 JNZ _00000129 ;if !ZF,----->v 00000129 u0 0000F9 F6C1 01 TEST CL,01h ; チ. 0000FC 74 2B JZ _00000129 ;if ZF,----->v 00000129 t+ 0000FE 61 POPA ; a _000000FF 60 PUSHA ; ` 000100 6A 00 PUSH 00h ; j. 000102 6A 00 PUSH 00h ; j. 000104 FF76 0A PUSH word ptr[BP+0Ah] ; .v. 000107 FF76 08 PUSH word ptr[BP+08h] ; .v. 00010A 6A 00 PUSH 00h ; j. 00010C 68 007C PUSH 7C00h ; h.| 00010F 6A 01 PUSH 01h ; j. 000111 6A 10 PUSH 10h ; j. 000113 B4 42 MOV AH,42h ; エB 000115 8BF4 MOV SI,SP ; 偶 000117 CD 13 INT 13h ;@D_42 = Extended Read ;INT 13h<=====> ヘ. 000119 61 POPA ; a 00011A 61 POPA ; a 00011B 73 0E JNB _0000012B ;if !CF,----->v 0000012B s. 00011D 4F DEC DI ; O 00011E 74 0B JZ _0000012B ;if ZF,----->v 0000012B t. 000120 32E4 XOR AH,AH ; 2. 000122 8A56 00 MOV DL,byte ptr[BP+00h] ; 碍. 000125 CD 13 INT 13h ;@D_00 = Disk Reset ;INT 13h<=====> ヘ. 000127 EB D6 JMP _000000FF ;----->^ 000000FF ・ _00000129 61 POPA ; a 00012A F9 STC ; . _0000012B C3 RET ;<===== テ 00012C 496E76616C696420 DB 'I','n','v','a','l','i','d',' ' ;?? Invalid 000134 706172746974696F DB 'p','a','r','t','i','t','i','o' ;?? partitio 00013C 6E207461626C6500 DB 'n',' ','t','a','b','l','e',00h ;?? n table. 000144 4572726F72206C6F DB 'E','r','r','o','r',' ','l','o' ;?? Error lo 00014C 6164696E67206F70 DB 'a','d','i','n','g',' ','o','p' ;?? ading op 000154 65726174696E6720 DB 'e','r','a','t','i','n','g',' ' ;?? erating 00015C 73797374656D004D DB 's','y','s','t','e','m',00h,'M' ;?? system.M 000164 697373696E67206F DB 'i','s','s','i','n','g',' ','o' ;?? issing o 00016C 7065726174696E67 DB 'p','e','r','a','t','i','n','g' ;?? perating 000174 2073797374656D00 DB ' ','s','y','s','t','e','m',00h ;?? system. 00017C 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000184 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00018C 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 000194 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 00019C 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001A4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001AC 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001B4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001BC 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001C4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001CC 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001D4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001DC 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001E4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001EC 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001F4 0000000000000000 DB 00h,00h,00h,00h,00h,00h,00h,00h ;?? ........ 0001FC 00000000 DB 00h,00h,00h,00h ;?? .... |
FAT32対応版の機能を一通り包含した上、どの領域に対しても使用可能であれば、LBAモードを使用するという特徴を持っている。
機能的な違いとしては、上記くらいしか確認できなかったが、次のような動作上の違いを確認した。FAT32対応版以前では、読み込んだブートセクターが無効だった場合、「Missing operating system」というエラーメッセージを出力ていたが、このバージョンのローダの場合、その場合でも「Error loading operating system」というエラーメッセージを出力した。いろいろ実験したが、「Missing operating system」というエラーメッセージを出力されることは、結局できなかった。これは何かバッグっぽい気もするが。
このようにブートストラップローダにもバージョンがあり、インストールの仕方、インストールされる場面によって違うので、環境移行の場合や、障害復旧時には気をつける必要がある。まあ、本格的なマルチブートを行っている人は、ブートストラップローダを使っていないだろうから、多くの場合問題ないだろうが。